/*****************************************************************************
 *  ENTROPY - emerging network to reduce orwellian potency yield
 *
 *  Copyright (C) 2002 Juergen Buchmueller <pullmoll@stop1984.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software Foundation,
 *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 *	$Id: funclib.c,v 1.2 2005/07/12 23:12:29 pullmoll Exp $
 *****************************************************************************/
#include "funclib.h"

#include <ctype.h>

#if	!HAVE_UTIMES
#include <utime.h>
#endif

#if	!HAVE_GETPAGESIZE
int getpagesize(void)
{
#ifdef	_SC_PAGESIZE
	/* sysconf() is POSIX standard; try it first */
	int pgsz = (int)sysconf(_SC_PAGESIZE);

	if (pgsz > 0)
		return pgsz;

	/* but if it returns <= 0, we have to fall back... */
#endif

#if	defined(PAGE_SIZE)
	return PAGE_SIZE;
#else
	return 4096; /* make an educated guess */
#endif
}
#endif

#if	!HAVE_STRTOULL
uint64_t strtoull(const char *nptr, char **endptr, int base) {
	const char *cursor = nptr;
	unsigned int ubase = base;
	uint64_t result = 0;
	uint64_t maxval;
	unsigned int maxrem;
	unsigned int ch;
	int negative = 0;
	int found = 0;

	while (isspace(*cursor))
		++cursor;

	switch (*cursor) {
	case '-':
		negative = 1;
	case '+':
		++cursor;
	default:
		break;
	}

	if ((ubase == 0 || ubase == 16) && cursor[0] == '0' && (cursor[1] == 'x' || cursor[1] == 'X')) {
		ubase = 16;
		cursor += 2;
	} else if (base == 0)
		ubase = (cursor[0] == '0') ? 8 : 10;

	maxval = ULLONG_MAX / ubase;
	maxrem = (unsigned int)(ULLONG_MAX % ubase);

	while ((ch = *cursor++) != 0) {
		if (isdigit(ch))
			ch -= '0';
		else if (isalpha(ch))
			ch = toupper(ch) - 'A' + 10;
		else
			break;

		if (ch >= ubase)
			break;

		if (result > maxval || (result == maxval && ch > maxrem)) {
			result = ULLONG_MAX;
			errno = ERANGE;
			break;
		}

		++found;
		result *= ubase;
		result += ch;
	}

	if (negative && found)
		result = (uint64_t)-((int64_t)result);

	if (endptr)
		*endptr = (char *)(found ? (cursor - 1) : nptr);

	return result;
}
#endif

#if	!HAVE_TIMEGM
time_t timegm(struct tm *tm)
{
	time_t time_temp;
	struct tm *tm_temp;

	if (NULL == tm) {
		errno = EINVAL;
		return -1;
	}
	time_temp = mktime(tm);
	tm_temp = gmtime(&time_temp);
	return (time_t)(time_temp + (time_temp - mktime(tm_temp)));
}
#endif

#if	!HAVE_UTIMES
int utimes(const char *file, const struct timeval *times)
{
	if (times != NULL) {
		struct utimbuf tb;

		tb.actime = times[0].tv_sec;
		tb.modtime = times[1].tv_sec;

		return utime(file, &tb);
	}
	return utime(file, NULL);
}
#endif
